use std::path::PathBuf;

use anyhow::Result;
use javy_codegen::{Generator, JS, LinkingKind, Plugin, WitOptions};

#[tokio::test]
async fn test_empty() -> Result<()> {
    // Load valid JS from file.
    let js = JS::from_file(
        &cargo_manifest_dir()
            .join("tests")
            .join("sample-scripts")
            .join("empty.js"),
    )?;

    // Configure code generator.
    let mut generator = Generator::new(default_plugin()?);
    generator.linking(LinkingKind::Static);

    // Generate valid Wasm module.
    let wasm = generator.generate(&js).await?;

    // Verify generated bytes are valid Wasm.
    walrus::Module::from_buffer(wasm.as_slice())?;

    Ok(())
}

#[tokio::test]
async fn test_snapshot_for_dynamically_linked_module() -> Result<()> {
    let sample_scripts = sample_scripts_dir();
    let js = JS::from_file(&sample_scripts.join("exported-functions.js"))?;
    let wasm = Generator::new(default_plugin()?)
        .linking(LinkingKind::Dynamic)
        .wit_opts(WitOptions::from_tuple((
            Some(sample_scripts.join("exported-functions.wit")),
            Some("exported-logs".into()),
        ))?)
        .producer_version("snapshot".into())
        .generate(&js)
        .await?;
    let wat = wasmprinter::print_bytes(wasm)?;
    insta::assert_snapshot!("default_dynamic", wat);
    Ok(())
}

fn cargo_manifest_dir() -> PathBuf {
    PathBuf::from(env!("CARGO_MANIFEST_DIR"))
}

fn sample_scripts_dir() -> PathBuf {
    cargo_manifest_dir().join("tests").join("sample-scripts")
}

fn default_plugin() -> Result<Plugin> {
    Plugin::new_from_path(
        cargo_manifest_dir()
            .join("..")
            .join("..")
            .join("target")
            .join("wasm32-wasip1")
            .join("release")
            .join("plugin_wizened.wasm"),
    )
}
